import { FolderOpenOutlined, FolderOutlined } from '@ant-design/icons'
import { ActionType } from '@ant-design/pro-components'
import PageList, { PageProColumns } from '@common/components/aoplatform/PageList.tsx'
import TableBtnWithPermission from '@common/components/aoplatform/TableBtnWithPermission.tsx'
import WithPermission from '@common/components/aoplatform/WithPermission.tsx'
import { BasicResponse, COLUMNS_TITLE, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const.tsx'
import { PERMISSION_DEFINITION } from '@common/const/permissions.ts'
import { EntityItem } from '@common/const/type.ts'
import { useBreadcrumb } from '@common/contexts/BreadcrumbContext.tsx'
import { useGlobalContext } from '@common/contexts/GlobalStateContext.tsx'
import { useFetch } from '@common/hooks/http.ts'
import { $t } from '@common/locales/index.ts'
import { handleDepartmentListToFilter } from '@common/utils/dataTransfer.ts'
import { checkAccess } from '@common/utils/permission.ts'
import { RouterParams } from '@core/components/aoplatform/RenderRoutes.tsx'
import { Alert, App, Button, Select, Tree, TreeProps } from 'antd'
import { DefaultOptionType } from 'antd/es/cascader/index'
import { ColumnFilterItem } from 'antd/es/table/interface'
import { DataNode } from 'antd/es/tree'
import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'
import { useOutletContext, useParams } from 'react-router-dom'
import { v4 as uuidv4 } from 'uuid'
import { MEMBER_TABLE_COLUMNS } from '../../const/member/const.tsx'
import {
  AddToDepartmentHandle,
  AddToDepartmentProps,
  DepartmentListItem,
  MemberDropdownModalHandle,
  MemberTableListItem
} from '../../const/member/type.ts'
import { MemberDropdownModal } from './MemberDropdownModal.tsx'

const AddToDepartment = forwardRef<AddToDepartmentHandle, AddToDepartmentProps>((props, ref) => {
  const { selectedUserIds } = props
  const [selectedKeys, setSelectedKeys] = useState<string[]>([])
  const [treeData, setTreeData] = useState<DataNode[]>()
  const { message } = App.useApp()
  const [expandedKeys, setExpandedKeys] = useState<string[]>([])
  const { fetchData } = useFetch()
  const { state } = useGlobalContext()
  const save: () => Promise<boolean | string> = () => {
    return new Promise((resolve, reject) => {
      fetchData<BasicResponse<null>>('user/department/member', {
        method: 'POST',
        eoBody: { userIds: selectedUserIds, departmentIds: selectedKeys },
        eoTransformKeys: ['departmentIds', 'userIds']
      })
        .then(response => {
          const { code, msg } = response
          if (code === STATUS_CODE.SUCCESS) {
            message.success(msg || $t(RESPONSE_TIPS.success))
            resolve(true)
          } else {
            message.error(msg || $t(RESPONSE_TIPS.error))
            reject(msg || $t(RESPONSE_TIPS.error))
          }
        })
        .catch(errorInfo => reject(errorInfo))
    })
  }

  useImperativeHandle(ref, () => ({
    save
  }))

  const getDepartmentList = () => {
    fetchData<BasicResponse<{ departments: DepartmentListItem[] }>>('user/departments', {
      method: 'GET'
    }).then(response => {
      const { code, data, msg } = response
      if (code === STATUS_CODE.SUCCESS) {
        data.departments.checkable = false
        data.departments.id = uuidv4()
        const newId = uuidv4()
        setTreeData([
          {
            ...data.departments,
            checkable: false,
            id: newId,
            children: data.departments.children.filter(
              x => x.id !== 'unknown' && x.id !== 'disable'
            )
          }
        ])
        setExpandedKeys([newId])
      } else {
        message.error(msg || $t(RESPONSE_TIPS.error))
        return { data: [], success: false }
      }
    })
  }

  const translatedTreeData = useMemo(
    () =>
      treeData?.map((x: DataNode) => ({
        ...x,
        name: $t((x as unknown as { name: string }).name),
        checkable: false, // 根节点不可选中
        children: x.children?.map(y => ({ ...y, checkable: true })) // 子节点可以选中
      })),
    [state.language, treeData]
  )

  const onCheck: TreeProps['onCheck'] = (checkedKeys, info) => {
    const selectedIds = Array.isArray(checkedKeys) ? checkedKeys : checkedKeys.checked || []
    setSelectedKeys(selectedIds)
  }

  useEffect(() => {
    getDepartmentList()
  }, [])

  return (
    <div>
      <Alert
        className="my-btnybase"
        message={$t('未激活、已禁用的成员无法加入到部门')}
        type="info"
      />
      <p className="font-bold leading-[24px]">
        {$t('请选择成员需要新加入的部门')}
        <span className="text-status_fail">*</span>
      </p>
      <div className="border-[1px] border-solid border-BORDER min-h-[200px]">
        <Tree
          checkable
          icon={(e: { expanded: boolean }) =>
            e.expanded ? <FolderOpenOutlined /> : <FolderOutlined />
          }
          showIcon={true}
          checkStrictly={true}
          selectable={false}
          onCheck={onCheck}
          onExpand={(expandedKeys: string[]) => {
            setExpandedKeys(expandedKeys)
          }}
          treeData={translatedTreeData}
          selectedKeys={[selectedKeys]}
          expandedKeys={expandedKeys}
          fieldNames={{ title: 'name', key: 'id', children: 'children' }}
        />
      </div>
    </div>
  )
})

const MemberList = () => {
  const { memberGroupId } = useParams<RouterParams>()
  const [searchWord, setSearchWord] = useState<string>('')
  const { modal, message } = App.useApp()
  // const [confirmLoading, setConfirmLoading] = useState(false);
  const [init, setInit] = useState<boolean>(true)
  const { fetchData } = useFetch()
  const [tableHttpReload, setTableHttpReload] = useState(true)
  const [tableListDataSource, setTableListDataSource] = useState<MemberTableListItem[]>([])
  const pageListRef = useRef<ActionType>(null)
  const { topGroupId, selectedDepartmentIds, refreshGroup, refreshTableCount } = useOutletContext<{
    topGroupId: string
    departmentList: DepartmentListItem[]
    selectedDepartmentIds: string[]
    refreshGroup: () => void
    refreshTableCount: number
  }>()
  const AddMemberRef = useRef<MemberDropdownModalHandle>(null)
  const EditMemberRef = useRef<MemberDropdownModalHandle>(null)
  const AddToDepRef = useRef<AddToDepartmentHandle>(null)
  const { setBreadcrumb } = useBreadcrumb()
  const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([])
  const [, setDepartmentValueEnum] = useState<ColumnFilterItem[]>([])
  const { accessData, state } = useGlobalContext()
  const [roleSelectableList, setRoleSelectableList] = useState<DefaultOptionType[]>([])

  const operation: PageProColumns<MemberTableListItem>[] = [
    {
      title: COLUMNS_TITLE.operate,
      key: 'option',
      btnNums: 1,
      fixed: 'right',
      valueType: 'option',
      render: (_: React.ReactNode, entity: MemberTableListItem) => [
        <TableBtnWithPermission
          access="system.organization.member.edit"
          key="edit"
          btnType="edit"
          onClick={() => {
            openModal('editMember', entity)
          }}
          btnTitle="编辑"
        />
      ]
    }
  ]

  const getMemberList = () => {
    if (!tableHttpReload) {
      setTableHttpReload(true)
      return Promise.resolve({
        data: tableListDataSource,
        success: true
      })
    }
    return fetchData<BasicResponse<{ members: MemberTableListItem }>>('user/accounts', {
      method: 'GET',
      eoParams: {
        keyword: searchWord,
        department: topGroupId === memberGroupId ? null : memberGroupId
      },
      eoTransformKeys: ['user_group']
    })
      .then(response => {
        const { code, data, msg } = response
        if (code === STATUS_CODE.SUCCESS) {
          setTableListDataSource(data.members)
          setInit(prev => (prev ? false : prev))
          return { data: data.members, success: true }
        } else {
          message.error(msg || $t(RESPONSE_TIPS.error))
          return { data: [], success: false }
        }
      })
      .catch(() => {
        return { data: [], success: false }
      })
  }

  const handleSelectChange = (newSelectedRowKeys: React.Key[]) => {
    setSelectedRowKeys(newSelectedRowKeys)
  }

  const handleRowClick = (entity: MemberTableListItem) => {
    if (entity.id === 'admin') return
    setSelectedRowKeys(prevData =>
      prevData?.indexOf(entity.id) === -1
        ? [...prevData, entity.id]
        : prevData.filter(x => x !== entity.id)
    )
  }

  const manualReloadTable = () => {
    setTableHttpReload(true) // 表格数据需要从后端接口获取
    pageListRef.current?.reload()
  }

  const handleMemberAction = (type: 'removeFromDep' | 'blocked' | 'activate' | 'delete') => {
    let url: string
    let method: string
    let params: { [k: string]: unknown } = {}
    let body: { [k: string]: unknown } = {}
    switch (type) {
      case 'removeFromDep':
        url = 'user/department/member/remove'
        method = 'POST'
        params = { department: memberGroupId }
        body = { userIds: selectedRowKeys }
        break
      case 'blocked':
        url = 'user/account/disable'
        method = 'POST'
        body = { userIds: selectedRowKeys }
        break
      case 'activate':
        url = 'user/account/enable'
        method = 'POST'
        body = { userIds: selectedRowKeys }
        break
      case 'delete':
        url = 'user/account'
        method = 'DELETE'
        params = { ids: JSON.stringify(selectedRowKeys) }
        body = { userIds: selectedRowKeys }
        break
    }

    return new Promise((resolve, reject) => {
      fetchData<BasicResponse<null>>(url, {
        method,
        eoTransformKeys: ['user_ids', 'userIds'],
        eoParams: params,
        eoBody: body
      })
        .then(response => {
          const { code, msg } = response
          if (code === STATUS_CODE.SUCCESS) {
            message.success(msg || $t(RESPONSE_TIPS.success))
            resolve(true)
          } else {
            message.error(msg || $t(RESPONSE_TIPS.error))
            reject(msg || $t(RESPONSE_TIPS.error))
          }
        })
        .catch(errorInfo => reject(errorInfo))
    })
  }

  const isActionAllowed = (
    type:
      | 'addMember'
      | 'editMember'
      | 'removeFromDep'
      | 'addToDep'
      | 'blocked'
      | 'activate'
      | 'delete'
  ) => {
    const actionToPermissionMap = {
      addMember: 'add',
      editMember: 'edit',
      removeFromDep: 'remove',
      addToDep: 'add',
      activate: 'block',
      blocked: 'block',
      delete: 'delete'
    }

    const action = actionToPermissionMap[type]
    const permission: keyof (typeof PERMISSION_DEFINITION)[0] = `system.organization.member.${action}`

    return !checkAccess(permission, accessData)
  }

  const openModal = (
    type: 'addMember' | 'editMember' | 'addToDep' | 'delete',
    entity?: MemberTableListItem
  ) => {
    let title: string = ''
    let content: string | React.ReactNode = ''
    switch (type) {
      case 'addMember':
        title = $t('添加账号')
        content = (
          <MemberDropdownModal
            topGroupId={topGroupId}
            ref={AddMemberRef}
            type={type}
            entity={{ id: memberGroupId, departmentIds: selectedDepartmentIds || [] }}
            selectedMemberGroupId={memberGroupId}
          />
        )
        break
      case 'editMember':
        title = $t('编辑成员信息')
        content = (
          <MemberDropdownModal
            topGroupId={topGroupId}
            ref={EditMemberRef}
            type={type}
            entity={entity}
          />
        )
        break
      case 'addToDep':
        title = $t('加入部门')
        content = (
          <AddToDepartment ref={AddToDepRef} selectedUserIds={selectedRowKeys as string[]} />
        )
        break
      case 'delete':
        title = $t('删除')
        content = <span>{$t('确定删除成员？此操作无法恢复，确认操作？')}</span>
        break
    }

    modal.confirm({
      title,
      content,
      onOk: () => {
        switch (type) {
          case 'addMember':
            return AddMemberRef.current?.save().then(res => {
              if (res === true) {
                refreshGroup && refreshGroup()
                manualReloadTable()
              }
            })
          case 'editMember':
            return EditMemberRef.current?.save().then(res => {
              if (res === true) {
                refreshGroup && refreshGroup()
                manualReloadTable()
              }
            })
          case 'addToDep':
            return AddToDepRef.current?.save().then(res => {
              if (res === true) {
                refreshGroup && refreshGroup()
                manualReloadTable()
              }
            })
          case 'delete':
            return handleMemberAction('delete').then(res => {
              if (res === true) {
                refreshGroup && refreshGroup()
                manualReloadTable()
              }
            })
        }
      },
      width: 600,
      okText: $t('确认'),
      okButtonProps: {
        disabled: isActionAllowed(type) || (type === 'editMember' && entity?.from === 'feishu')
      },
      cancelText: $t('取消'),
      closable: true,
      icon: <></>
    })
  }

  useEffect(() => {
    !init && manualReloadTable()
    setSelectedRowKeys([])
  }, [memberGroupId])

  useEffect(() => {
    getRoleList()
    setBreadcrumb([{ title: $t('成员与部门') }])
    getDepartmentList()
  }, [])

  // 监听外部刷新触发器
  useEffect(() => {
    if (refreshTableCount > 0) {
      manualReloadTable()
    }
  }, [refreshTableCount])

  const getDepartmentList = async () => {
    setDepartmentValueEnum([])
    const { code, data, msg } = await fetchData<BasicResponse<{ department: DepartmentListItem }>>(
      'simple/departments',
      { method: 'GET' }
    )
    if (code === STATUS_CODE.SUCCESS) {
      const tmpValueEnum: ColumnFilterItem[] = [
        {
          text: data.department.name,
          value: data.department.id,
          children: handleDepartmentListToFilter(data.department.children)
        }
      ]
      setDepartmentValueEnum(tmpValueEnum)
    } else {
      message.error(msg || $t(RESPONSE_TIPS.error))
    }
  }

  const changeMemberInfo = (value: string[], entity: MemberTableListItem) => {
    return new Promise((resolve, reject) => {
      fetchData<BasicResponse<null>>(`account/role`, {
        method: 'PUT',
        eoBody: { roles: value, users: [entity.id] }
      })
        .then(response => {
          const { code, msg } = response
          if (code === STATUS_CODE.SUCCESS) {
            message.success(msg || $t(RESPONSE_TIPS.success))
            resolve(true)
          } else {
            message.error(msg || $t(RESPONSE_TIPS.error))
            reject(msg || $t(RESPONSE_TIPS.error))
          }
        })
        .catch(errorInfo => reject(errorInfo))
    })
  }

  const getRoleList = () => {
    fetchData<BasicResponse<{ roles: Array<{ id: string; name: string }> }>>('simple/roles', {
      method: 'GET',
      eoParams: { group: 'system' }
    }).then(response => {
      const { code, data, msg } = response
      if (code === STATUS_CODE.SUCCESS) {
        setRoleSelectableList(data.roles)

        return
      } else {
        message.error(msg || $t(RESPONSE_TIPS.error))
      }
    })
  }

  const translatedCol = useMemo(
    () =>
      MEMBER_TABLE_COLUMNS.map(x => ({
        ...x,
        ...(x.dataIndex === 'roles'
          ? {
              render: (_, entity) => (
                <WithPermission access="system.organization.member.edit">
                  <Select
                    showSearch
                    optionFilterProp="label"
                    className="w-full"
                    mode="multiple"
                    value={entity.roles?.map((x: EntityItem) => x.id)}
                    options={roleSelectableList?.map((x: { id: string; name: string }) => ({
                      label: x.name,
                      value: x.id
                    }))}
                    onChange={value => {
                      changeMemberInfo(value, entity).then(res => {
                        if (res) manualReloadTable()
                      })
                    }}
                  />
                </WithPermission>
              ),
              filters: roleSelectableList?.map((x: { id: string; name: string }) => ({
                text: $t(x.name),
                value: x.id
              })),
              onFilter: (value: unknown, record: MemberTableListItem) => {
                return record.roles
                  ? record.roles?.map(x => x.id).indexOf(value as string) !== -1
                  : false
              }
            }
          : {}),
        ...(typeof x.title === 'string' ? { title: $t(x.title as string) } : {}),
        ...(x.dataIndex === 'enable'
          ? {
              valueEnum: new Map([
                [true, <span className="text-status_success">{$t('启用')}</span>],
                [false, <span className="text-status_fail">{$t('禁用')}</span>]
              ])
            }
          : {})
      })),
    [state.language, roleSelectableList]
  )

  return (
    <>
      <PageList
        id="global_member"
        ref={pageListRef}
        columns={[...translatedCol, ...operation]}
        request={() => getMemberList()}
        addNewBtnTitle={
          !memberGroupId || ['unknown', 'disable'].indexOf(memberGroupId?.toString()) === -1
            ? $t('添加账号')
            : ''
        }
        searchPlaceholder={$t('输入用户名、邮箱查找成员')}
        onAddNewBtnClick={() => {
          openModal('addMember')
        }}
        addNewBtnAccess="system.organization.member.add"
        rowSelection={{
          // selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
          selectedRowKeys,
          columnWidth: 40,
          onChange: handleSelectChange,
          getCheckboxProps: (record: MemberTableListItem) => ({
            disabled: record.id === 'admin', // Column configuration not to be checked
            name: record.name
          })
        }}
        onRowClick={handleRowClick}
        tableClickAccess="system.organization.member.edit"
        afterNewBtn={[
          selectedRowKeys.length > 0 && memberGroupId && (
            <WithPermission key="removeFromDepPermission" access="system.organization.member.edit">
              <Button
                className="mr-btnbase"
                key="removeFromDep"
                onClick={() =>
                  handleMemberAction('removeFromDep').then(res => {
                    if (res === true) {
                      refreshGroup && refreshGroup()
                      manualReloadTable()
                    }
                  })
                }
              >
                {$t('移出当前部门')}
              </Button>
            </WithPermission>
          ),
          selectedRowKeys.length > 0 && memberGroupId && (
            <WithPermission key="addToDepPermission" access="system.organization.member.edit">
              <Button className="mr-btnbase" key="addToDep" onClick={() => openModal('addToDep')}>
                {$t('加入部门')}
              </Button>
            </WithPermission>
          ),
          selectedRowKeys.length > 0 && memberGroupId !== 'disable' && (
            <WithPermission key="blockedPermission" access="system.organization.member.block">
              <Button
                className="mr-btnbase"
                key="blocked"
                onClick={() =>
                  handleMemberAction('blocked').then(res => {
                    if (res === true) {
                      refreshGroup && refreshGroup()
                      manualReloadTable()
                    }
                  })
                }
              >
                {$t('禁用成员')}
              </Button>
            </WithPermission>
          ),
          selectedRowKeys.length > 0 && (
            <WithPermission key="activatePermission" access="system.organization.member.block">
              <Button
                className="mr-btnbase"
                key="activate"
                onClick={() =>
                  handleMemberAction('activate').then(res => {
                    if (res === true) {
                      refreshGroup && refreshGroup()
                      manualReloadTable()
                    }
                  })
                }
              >
                {$t('启用成员')}
              </Button>
            </WithPermission>
          ),
          selectedRowKeys.length > 0 && (
            <WithPermission key="deletePermission" access="system.organization.member.delete">
              <Button className="mr-btnbase" key="delete" onClick={() => openModal('delete')}>
                {$t('删除成员')}
              </Button>
            </WithPermission>
          )
        ]}
        onSearchWordChange={e => {
          setSearchWord(e.target.value)
        }}
        onChange={() => {
          setTableHttpReload(false)
        }}
      />
    </>
  )
}
export default MemberList
